home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / games / IndiZone / blix / players.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  52.1 KB  |  2,005 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*________________________________________________________________
  18.  |
  19.  | players.c - does all the action of the game
  20.  |
  21.  | in here are the routines that make the mouse move, explode the
  22.  | bombs etc. init_players, and players_action are the two
  23.  | routines that do it.
  24.  | Call draw_players, to draw them on your screen.
  25.  |
  26.  | (c) Frans van Hoesel 1994, Xtreme Graphics Software
  27.  |
  28. */
  29.  
  30. #include <device.h>
  31. #include <gl/gl.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <sys/types.h>
  35. #include <string.h>
  36. #include <malloc.h>
  37. #include <math.h>
  38. #include <unistd.h>
  39.  
  40. #include "io.h"
  41. #include "IvtoGL.h"
  42. #include "blixvect.h"
  43. #include "lod.h"
  44. #include "maze.h"
  45. #include "players.h"
  46. #include "rand.h"
  47. #include "blixsound.h"
  48. #include "blix.h"
  49. #include "blixui.h"
  50.  
  51. extern node_t *the_nodes;
  52. extern int the_nnodes;
  53. extern int Lod;
  54. extern int putbomb;
  55. extern Matrix rotmat;
  56. int score = 0;
  57. int highscore = 0; 
  58. int mouse_dead = 0;
  59. float trackpoint[3] = { 0 , 1, 0 };    /* the point you last clicked */
  60.  
  61. /* MAXMONSTER is a limitation, to make sure we don't draw
  62.  * too many, because that would slow down the machine quite a lot
  63.  * (it would be nice to increase this number on fast machines)
  64.  */
  65. #define MAXMONSTER 20
  66.  
  67. /* type of actors involved in this game */
  68. enum ptypes  { NONE = 0, MOUSE, FISH, BONES, SPIDER, BOMB, MUSH, LIFT,
  69.     FIRE, DOOR };
  70.  
  71. /* type of action to perform in a call to do_some_actor */
  72. enum atype { IDLE = 1, MAGIC, KILL };
  73.  
  74.  
  75. static void remove_player(player_t *p);
  76. static int randnod(void);
  77. static player_t *add_player(int ptyp, int currnode, int prevnode);
  78. static void build_fire(int nodnum, int power);
  79. static void init_special(void);
  80.  
  81. static int allow_bombs = 0;
  82. static int lifts_destroyed = 0;
  83. static int active_lift = -1;
  84. static float mouse_pos[3] = { 0, 1, 0 };
  85. static player_t *first_player = NULL;
  86. static player_t *last_player = NULL;
  87. static player_t *null_player = NULL;
  88. static player_t *door_player = NULL;
  89. int monster_cnt = 0;
  90. static float prev_trackpoint[3] = {0, 1, 0};
  91. static player_t obj_definitions[] = {
  92.     { /* none */
  93.     0, 0, 0, 0, 0, { 0, -1, 0 }, { 1,  0,  0 }, 0, 0, 0, NULL, NULL
  94.     },
  95.     { /* mouse */
  96.     1, 12, 0, 0, 0, { 0, -1, 0 }, { 0.000000,  0.850651,  0.525731 },
  97.     0.023, 1420, 1420, NULL, NULL
  98.     },
  99.     { /* fish */
  100.         2, 1, 0, 0, 0, { 0, -1, 0}, { 1, 0, 0}, 0.023, 900, 901, NULL, NULL
  101.     },
  102.     { /* bones */
  103.         3, 1, 0, 0, 0, { 0, -1, 0}, { 1, 0, 0}, 0.034, 300, 299, NULL, NULL
  104.     },
  105.     { /* spider */
  106.         4, 1, 0, 0, 0, { 0, -1, 0}, { 1, 0, 0}, 0.017, 900, 901, NULL, NULL
  107.     },
  108.     { /* bomb */
  109.         5, 1, 2, 0, 0, { 0, -1, 0}, { 1, 0, 0}, 0.0, 900, 901, NULL, NULL
  110.     },
  111.     { /* mushroom */
  112.         6, 1, 1, 0, 0, { 0, -1, 0}, { 1, 0, 0}, 0.0, 900, 901, NULL, NULL
  113.     },
  114.     { /* lift */
  115.         7, 1, 0, 0, 0, { 0, -1, 0}, { 1, 0, 0}, 0.0, 900, 901, NULL, NULL
  116.     },
  117.     { /* fire1 */
  118.         8, 1, 14, 0, 0, { 0, -1, 0}, { 1, 0, 0}, 0.0, 900, 901, NULL, NULL
  119.     },
  120.     { /* door */
  121.         9, 1, 0, 0, 0, { 0, -1, 0}, { 1, 0, 0}, 0.0, 900, 901, NULL, NULL
  122.     }
  123.    };
  124.  
  125. /*__________________________________________________________________
  126.  |
  127.  | randnod - returns a random node
  128.  |
  129.  | the nodenumber returned is a free node, not on a crossing
  130.  |
  131. */
  132.  
  133. static int randnod(void) {
  134.  
  135.     int n;
  136.     node_t *nod;
  137.     do {
  138.     n = (int) (random() % the_nnodes);
  139.     nod = &(the_nodes[n]);
  140.     } while (nod->player != null_player || nod->cnt != 2 ||
  141.         the_nodes[nod->c[0]].player != null_player ||
  142.         the_nodes[nod->c[1]].player != null_player ) ;
  143.     return n;
  144. }
  145.  
  146. /*_______________________________________________________________________
  147.  |
  148.  | do_step - make the actors walk
  149.  |
  150.  | the maze path which the monsters follow is divided into nodes; actors
  151.  | can only do things when they are at a node. The stages in in between the
  152.  | nodes are interpolated in this routine.
  153.  |
  154. */
  155.  
  156. static void do_step(player_t *p) {
  157.     float *p1;
  158.     float v1[3];
  159.     float l, factor;
  160.     node_t *nod, *pnod;
  161.     
  162.     nod = &(the_nodes[p->currnode]);
  163.     p1 = nod->pos;
  164.     pnod = &(the_nodes[p->prevnode]);
  165.     vsub(p1, p->pos,  v1);
  166.     l = vlength(v1);
  167.     if (l < p->speed * 1.1) {
  168.     /* if next node is very close, step to node position */
  169.     vcopy(p1, p->pos);
  170.     vcross(p1, pnod->pos, p->dir);
  171.     vcross(p1, p->dir, p->dir);
  172.     /*vsub(p1, pnod->pos, p->dir);*/
  173.     vnormal(p->dir);
  174.     /* when the actor is in between two nodes, both nodes have stored
  175.      * the actor in their player field. Remove it from the node
  176.      * when you just left it completely
  177.      */
  178.     if (pnod->player->player_type == p->player_type) {
  179.         pnod->player = null_player;
  180.     }
  181.     p->prevnode = p->currnode;
  182.     } else {
  183.     /* do an intermediate step, and adjust direction slightly */
  184.     factor = p->speed / l;
  185.     vscalar(v1, factor);
  186.     vadd(p->pos, v1, p->pos);
  187.     vnormal(p->pos);
  188.     vsub(p1, pnod->pos, v1);
  189.     vnormal(v1);
  190.     vsub(v1, p->dir, v1);
  191.     vscalar(v1, factor);
  192.     vadd(p->dir, v1, p->dir);
  193.     vcross(p->dir, p->pos, v1);
  194.     vcross(p->pos, v1, p->dir);
  195.     vnormal(p->dir);
  196.     }
  197.     nod->player = p;
  198. }
  199.  
  200. /*_________________________________________________________________________
  201.  |
  202.  | path_to_track - find a 'good' route towards the tracking point
  203.  |
  204.  | It's a little recursive routine that finds the best path towards
  205.  | the tracking point, while never step away from it. This routine
  206.  | might be called a few times too often (I could store the path. as
  207.  | long as the tracking point doesn't change)
  208.  |
  209. */
  210.  
  211. static int path_to_track(int nod, float *dist) {
  212.     node_t *node;
  213.     
  214.     int nnod, i;
  215.     float nd, nd2;
  216.     float ndist, ldist, mdist;
  217.     
  218.     node = &(the_nodes[nod]);
  219.     ndist = *dist;
  220.     ldist = *dist;
  221.     mdist = *dist;
  222.     for (i=0; i <node->cnt; i++) {
  223.     nnod = node->c[i];
  224.     nd = vdistance2(the_nodes[nnod].pos, trackpoint);
  225.     if (nd < ldist) {
  226.         nd2 = nd;
  227.         path_to_track(nnod, &nd2);
  228.         if (nd2 < ndist) {
  229.             ndist = nd2;
  230.             nod = nnod;
  231.             mdist = nd;
  232.         } else if (nd2 ==  ndist && nd < mdist) {
  233.             ndist = nd2;
  234.             nod = nnod;
  235.             mdist = nd;
  236.         }
  237.     }
  238.     }
  239.     *dist = ndist;
  240.     return nod;
  241. }
  242.  
  243. /*_________________________________________________________________________
  244.  |
  245.  | path_to_mouse - find a 'good' route towards the mouse
  246.  |
  247.  | It's a little recursive routine that finds the best path towards
  248.  | the point, were the mouse is, while never step away from it.
  249.  |
  250. */
  251.  
  252. static int path_to_mouse(int nod, float *dist) {
  253.     node_t *node;
  254.     
  255.     int nnod, i;
  256.     float nd, nd2;
  257.     float ndist, ldist, mdist;
  258.     
  259.     node = &(the_nodes[nod]);
  260.     ndist = *dist;
  261.     ldist = *dist;
  262.     mdist = *dist;
  263.     for (i=0; i <node->cnt; i++) {
  264.     nnod = node->c[i];
  265.     nd = vdistance2(the_nodes[nnod].pos, mouse_pos);
  266.     if (nd < ldist) {
  267.         nd2 = nd;
  268.         path_to_mouse(nnod, &nd2);
  269.         if (nd2 < ndist) {
  270.             ndist = nd2;
  271.             nod = nnod;
  272.             mdist = nd;
  273.         } else if (nd2 ==  ndist && nd < mdist) {
  274.             ndist = nd2;
  275.             nod = nnod;
  276.             mdist = nd;
  277.         }
  278.     }
  279.     }
  280.     *dist = ndist;
  281.     return nod;
  282. }
  283.  
  284. /*________________________________________________________________________
  285.  |
  286.  | do_mouse - handle all the acting of the mouse
  287.  |
  288. */
  289.  
  290. static void do_mouse(player_t *p, int action) {
  291.     node_t *nod, *nnod;
  292.     int i;
  293.     int nextnod;
  294.     float dist, ndist;
  295.     player_t *play;
  296.     float v1[3], v2[3];
  297.     
  298.     switch (action) {
  299.     case IDLE:                /* idle */
  300.         switch (p->stage) {
  301.         case 12:
  302.             /* mouse is standing still */
  303.             if (putbomb && allow_bombs) {
  304.             p->stage = 7;
  305.             p->stage_cnt = -1;
  306.             p->curr_object = 5108;
  307.             break;
  308.             } else {
  309.             if (veq(trackpoint, prev_trackpoint)) {
  310.                 p->curr_object = 5101;
  311.                 if (Lod < LIVE_FIGURES) {
  312.                 p->curr_object = p->base_object;
  313.                 }
  314.                 break;
  315.             }
  316.             }
  317.         case 6:
  318.             p->stage = 0;
  319.         case 1:
  320.         case 2:
  321.         case 3:
  322.         case 4:
  323.         case 5:
  324.             p->stage++;
  325.             /* mouse is walking and position is exactly on node */
  326.             if (p->currnode == p->prevnode) {
  327.             if (putbomb && allow_bombs) {
  328.                 p->stage = 7;
  329.                 p->stage_cnt = -1;
  330.                 p->curr_object = 5108;
  331.                 break;
  332.             }
  333.             /* find the next node that makes the distance
  334.              * to the tracking point the closest possible
  335.              */
  336.             nod = &(the_nodes[p->currnode]);
  337.             nextnod = p->currnode;
  338.             dist = vdistance2(the_nodes[nextnod].pos, trackpoint);
  339.             nextnod = path_to_track(p->currnode, &dist);
  340.             play = the_nodes[nextnod].player;
  341.             if (play != null_player) {
  342.                 if ((play->player_type == SPIDER ||
  343.                     play->player_type == FISH ||
  344.                     play->player_type == BONES) &&
  345.                     !mouse_dead ) {
  346.                 /* you just stepped into a deadly monster */
  347.                 sfx(SFX_DONK);
  348.                 do_mouse(p, KILL);
  349.                 return ;
  350.                 } else if (play->player_type == DOOR ||
  351.                     play->player_type == MUSH) {
  352.                 /* your path is blocked, but do the
  353.                  * step that makes your distance to the 
  354.                  * trackpoint smaller
  355.                  */
  356.                 nextnod = p->currnode;
  357.                 dist = vdistance2(the_nodes[nextnod].pos,
  358.                     trackpoint);
  359.                 i = 0;
  360.                 while (i < nod->cnt) {
  361.                     if (the_nodes[nod->c[i]].player 
  362.                         == null_player) {
  363.                     ndist = vdistance2(
  364.                         the_nodes[nod->c[i]].pos,
  365.                         trackpoint);
  366.                     if (ndist < dist) {
  367.                         dist = ndist;
  368.                         nextnod = nod->c[i];
  369.                     }
  370.                     }
  371.                     i++;
  372.                 }
  373.                 play = the_nodes[nextnod].player;
  374.                 if (play != null_player) {
  375.                     if ((play->player_type == SPIDER ||
  376.                         play->player_type == FISH ||
  377.                         play->player_type == BONES) &&
  378.                         !mouse_dead ) {
  379.                     /* unfortunatly you stepped the wrong
  380.                      * way
  381.                      */
  382.                     sfx(SFX_DONK);
  383.                     do_mouse(p, KILL);
  384.                     return ;
  385.                     }
  386.                 }
  387.                 } else {  
  388.                 /* mouse stops moving */
  389.                 nextnod = p->currnode;
  390.                 }
  391.                 
  392.             }
  393.             
  394.             if (nextnod == p->currnode) {
  395.                 /* stop moving the mouse */
  396.                 p->stage = 12;
  397.                 p->curr_object = p->base_object + 1;
  398.                 vcopy(trackpoint, prev_trackpoint);
  399.             } else {
  400.                 /* did you step on one of the magic footsteps ? */
  401.                 if (the_nodes[nextnod].special.b.magic != 0) {
  402.                 do_player(
  403.                     the_nodes[the_nodes[nextnod].special.b.magic].player,
  404.                     MAGIC);
  405.                 }
  406.                 nnod = & (the_nodes[nextnod]);
  407.                 vsub(nnod->pos, nod->pos, v1);
  408.                 if (vdot(v1, p->dir) < -0.04) {
  409.                 if (nod->cnt >1 ) {
  410.                     if (nextnod == nod->c[0]) {
  411.                     vsub(the_nodes[nod->c[1]].pos, nnod->pos, v2);
  412.                     } else {
  413.                     vsub(the_nodes[nod->c[0]].pos, nnod->pos, v2);
  414.                     }
  415.                     vscalar(v1, 1.6);
  416.                 } else {
  417.                     vcross(nnod->pos, nod->pos, v2);
  418.                     vscalar(v1, -0.3 / vlength(v1));
  419.                 }
  420.                 vadd(v1, v2, p->dir);
  421.                 vcross(p->dir, p->pos, v1);
  422.                 vcross(p->pos, v1, p->dir);
  423.                 vnormal(p->dir);
  424.                     p->currnode = nextnod;
  425.                 } else {
  426.                 p->currnode = nextnod;
  427.                     do_step(p);
  428.                 }
  429.                 p->curr_object = p->base_object + p->stage+1; 
  430.             }
  431.             } else {
  432.             /* keep on walking from prevnode to currnode */
  433.             do_step(p); 
  434.             p->curr_object = p->base_object + p->stage+1; 
  435.             }            
  436.             if (Lod < LIVE_FIGURES) {
  437.             p->curr_object = p->base_object;
  438.             }
  439.             break;
  440.         case 7:
  441.             if (p->stage_cnt-- < 0) {
  442.             p->stage = 8;
  443.             p->curr_object = 5109;
  444.             p->stage_cnt = -1;
  445.             } else {
  446.             p->curr_object = 5108;
  447.             }
  448.             break;
  449.         case 8:            /* put a bomb */
  450.             if (p->stage_cnt-- < 0) {
  451.             p->stage = 9;
  452.             p->curr_object = 5110;
  453.             p->stage_cnt = -1;
  454.             /* find forward bend position */
  455.             nod = the_nodes+ p->currnode;
  456.             nextnod = p->currnode;
  457.             dist =10;
  458.             i = 0;
  459.             vcopy(p->dir, v1);
  460.             vscalar(v1, 0.1);
  461.             vadd(p->pos, v1, v1);
  462.             while (i < nod->cnt) {
  463.                 ndist = vdistance2(the_nodes[nod->c[i]].pos, v1);
  464.                 if (ndist < dist) {
  465.                 dist = ndist;
  466.                 nextnod = nod->c[i];
  467.                 }
  468.                 i++;
  469.             }
  470.             if (the_nodes[nextnod].player == null_player) {
  471.                 the_nodes[nextnod].player =
  472.                 add_player(BOMB, nextnod, p->currnode);
  473.             } else if (the_nodes[nextnod].player->player_type == LIFT &&
  474.                 the_nodes[the_nodes[nextnod].c[1]].player ==
  475.                     null_player) {
  476.                 /* the clause makes it possible to put a bomb inside
  477.                  * a lift (there is an extra node for this in the data
  478.                  * exactly at the same possition as the lift) The node
  479.                  * to put that bomb is always in the_nodes[nextnod].c[1]
  480.                  */
  481.                 the_nodes[the_nodes[nextnod].c[1]].player =
  482.                 add_player(BOMB, the_nodes[nextnod].c[1],
  483.                     nextnod);
  484.             }
  485.             } else {
  486.             p->curr_object = 5109;
  487.             }
  488.             break;
  489.         case 9:
  490.             if (p->stage_cnt-- < 0) {
  491.             p->stage = 10;
  492.             p->curr_object = 5109;
  493.             p->stage_cnt = -1;
  494.             } else {
  495.             p->curr_object = 5110;
  496.             }
  497.             break;
  498.         case 10:
  499.             if (p->stage_cnt-- < 0) {
  500.             p->stage = 11;
  501.             p->curr_object = 5108;
  502.             p->stage_cnt = -1;
  503.             } else {
  504.             p->curr_object = 5109;
  505.             }
  506.             break;
  507.         case 11:
  508.             if (p->stage_cnt-- < 0) {
  509.             p->stage = 12;
  510.             p->curr_object = 5101;
  511.             p->stage_cnt = 0;
  512.             putbomb = 0;
  513.             } else {
  514.             p->curr_object = 5108;
  515.             }
  516.             break;
  517.         } /* switch stage */
  518.         break;
  519.     case KILL:
  520.         /* you are dead! 
  521.          * Note that the mouse_dead variable is incremented at each frame
  522.          * to do some animation in the dead phase. That animations is
  523.          * a later hack, and didn't fit well in the do_mouse routine.
  524.          */
  525.         if (!mouse_dead) {    
  526.         mouse_dead = 1;
  527.         }
  528.         break;
  529.     } /* switch action */
  530.     
  531.     /* record the mouse position, so the monster know how to hunt you */
  532.     mouse_pos[0] = p->pos[0];
  533.     mouse_pos[1] = p->pos[1];
  534.     mouse_pos[2] = p->pos[2];
  535. }
  536.  
  537.  
  538. /*_________________________________________________________________________
  539.  |
  540.  | do_fish - make the fish fly
  541.  |
  542.  | this routine isn't much different from do_spider or do_bones
  543.  | (there are slight variations to give each monster some character)
  544. */
  545.  
  546. static void do_fish(player_t *p, int action) {
  547.     node_t *nod;
  548.     int i;
  549.     int nextnod;
  550.     float dist, ndist;
  551.     player_t *play;
  552.     float v1[3];
  553.     
  554.     switch (action) {
  555.     case 1:                /* idle */
  556.         switch (p->stage) {
  557.         case 7:
  558.             p->stage = 0;
  559.         case 1:
  560.         case 2:
  561.         case 3:
  562.         case 4:
  563.         case 5:
  564.         case 6:
  565.             if (p->currnode == p->prevnode) {
  566.             /* find the next node that makes the distance
  567.              * to the tracking point the closest possible
  568.              */
  569.             nod = the_nodes+ p->currnode;
  570.             nextnod = p->currnode;
  571.             dist =10;
  572.             i = (int) random() % 20;
  573.             /* if you are on a crossing make the fish walk
  574.              * towards the mouse, or let it walk straight ahead
  575.              * in its current direction
  576.              */
  577.             if (nod->cnt > 2 && i < 5 + lifts_destroyed / 5) {
  578.                 /* walk in the direction of the mouse; however
  579.                  * there is a small change to do a random step
  580.                  */
  581.                 if ( i == 0) {
  582.                 v1[0] = frand();
  583.                 v1[1] = v1[0]+0.0001;
  584.                 v1[2] = v1[1];
  585.                 vnormal(v1);
  586.                 }
  587.                 vcopy(mouse_pos, v1);
  588.             } else {
  589.                 vadd(p->pos, p->dir, v1);
  590.             }
  591.             i = 0;
  592.             
  593.             while (i < nod->cnt) {
  594.                 play = the_nodes[nod->c[i]].player;
  595.             if (play != null_player && play->player_type != MOUSE) {
  596.                 i++;
  597.                 continue;
  598.                 }
  599.                 
  600.                 ndist = vdistance2(the_nodes[nod->c[i]].pos, v1);
  601.                 if (ndist < dist) {
  602.                 dist = ndist;
  603.                 nextnod = nod->c[i];
  604.                 }
  605.                 i++;
  606.             }
  607.             if (nextnod == p->currnode) {
  608.                 /* stop moving the fish */
  609.                 p->stage++;
  610.             } else {
  611.                 p->stage++;
  612.                 p->currnode = nextnod;
  613.                 if (the_nodes[nextnod].player->player_type 
  614.                     == MOUSE) {
  615.                 do_step(p);
  616.                 sfx(SFX_DONK);
  617.                 do_mouse(the_nodes[nextnod].player, KILL);
  618.                 }
  619.                 vsub(the_nodes[nextnod].pos,
  620.                     the_nodes[p->prevnode].pos, v1);
  621.                 if (vdot(v1, p->dir) < 0) {
  622.                 vcross(the_nodes[nextnod].pos,
  623.                     the_nodes[p->prevnode].pos, p->dir);
  624.                 vnormal(v1);
  625.                 vscalar(v1, -0.3);
  626.                 vadd(p->dir, v1, p->dir);
  627.                 vnormal(p->dir);
  628.                 }
  629.                 do_step(p);
  630.                 p->curr_object = p->base_object + p->stage; 
  631.             }
  632.             } else {
  633.             /* keep on walking from prevnode to currnode */
  634.             p->stage++;
  635.             do_step(p); 
  636.             p->curr_object = p->base_object + p->stage; 
  637.             }
  638.             if (Lod < LIVE_FIGURES) {
  639.             p->curr_object = p->base_object;
  640.             }
  641.             break;
  642.         case 8:
  643.             if (p->stage_cnt--< 0) {
  644.             the_nodes[p->currnode].player = null_player;
  645.             remove_player(p);
  646.             monster_cnt --;
  647.             } else {
  648.             p->curr_object = 5208;
  649.             }
  650.         } /* switch stage */
  651.         break;
  652.     case KILL:
  653.         if (p->stage != 8) {
  654.         p->stage = 8;
  655.         p->curr_object = 5208;
  656.         p->stage_cnt = 13;
  657.         score += 50;
  658.         }
  659.         break;
  660.     } /* switch action */
  661.     ;
  662. }
  663.  
  664.  
  665. /*_______________________________________________________________________
  666.  |
  667.  | do_bones - handle the very fast bones figure
  668.  |
  669.  | this routines is very much like do_fish or do_spider
  670. */
  671.  
  672. static void do_bones(player_t *p, int action) {
  673.     node_t *nod;
  674.     int i;
  675.     int nextnod;
  676.     float dist, ndist;
  677.     player_t *play;
  678.     float v1[3];
  679.     
  680.     switch (action) {
  681.     case IDLE:                /* idle */
  682.         switch (p->stage) {
  683.         case 6:
  684.             p->stage = 0;
  685.         case 1:
  686.         case 2:
  687.         case 3:
  688.         case 4:
  689.         case 5:
  690.             if (p->currnode == p->prevnode) {
  691.             /* find the next node that makes the distance
  692.              * to the tracking point the closest possible
  693.              */
  694.             nod = the_nodes+ p->currnode;
  695.             nextnod = p->currnode;
  696.             dist =10;
  697.             i = (int) random() % 20;
  698.             if (nod->cnt > 2 && i < 5 + lifts_destroyed / 10) {
  699.                 if ( i == 0) {
  700.                 v1[0] = frand();
  701.                 v1[1] = v1[0]+0.0001;
  702.                 v1[2] = v1[1];
  703.                 vnormal(v1);
  704.                 }
  705.                 vcopy(mouse_pos, v1);
  706.             } else {
  707.                 vadd(p->pos, p->dir, v1);
  708.             }
  709.             i = 0;
  710.             while (i < nod->cnt) {
  711.                 play = the_nodes[nod->c[i]].player;
  712.                 if (play != null_player && play->player_type != MOUSE) {
  713.                 i++;
  714.                 continue;
  715.                 }
  716.                 
  717.                 ndist = vdistance2(the_nodes[nod->c[i]].pos, v1);
  718.                 if (ndist < dist) {
  719.                 dist = ndist;
  720.                 nextnod = nod->c[i];
  721.                 }
  722.                 i++;
  723.             }
  724.             if (nextnod == p->currnode) {
  725.                 /* stop moving the bones */
  726.                 p->stage++;
  727.             } else {
  728.                 p->stage++;
  729.                 p->currnode = nextnod;
  730.                 if (the_nodes[nextnod].player->player_type 
  731.                     == MOUSE) {
  732.                 do_step(p);
  733.                 sfx(SFX_DONK);
  734.                 do_mouse(the_nodes[nextnod].player, KILL);
  735.                 }
  736.                 vsub(the_nodes[nextnod].pos,
  737.                     the_nodes[p->prevnode].pos, v1);
  738.                 if (vdot(v1, p->dir) < 0) {
  739.                 vcross(the_nodes[nextnod].pos,
  740.                     the_nodes[p->prevnode].pos, p->dir);
  741.                 vnormal(v1);
  742.                 vscalar(v1, -0.3);
  743.                 vadd(p->dir, v1, p->dir);
  744.                 vnormal(p->dir);
  745.                 }
  746.                 do_step(p);
  747.                 p->curr_object = p->base_object + p->stage; 
  748.             }
  749.             } else {
  750.             /* keep on walking from prevnode to currnode */
  751.             p->stage++;
  752.             do_step(p); 
  753.             p->curr_object = p->base_object + p->stage; 
  754.             }
  755.             if (Lod < LIVE_FIGURES) {
  756.             p->curr_object = p->base_object;
  757.             }
  758.             break;
  759.         case 7:
  760.             /* killed, showing score */
  761.             if (p->stage_cnt-- < 0) {
  762.             the_nodes[p->currnode].player = 0;
  763.             remove_player(p);
  764.             monster_cnt--;
  765.             return;
  766.             } else {
  767.             p->curr_object = 5307;
  768.             }
  769.             break;
  770.         } /* switch stage */
  771.         break;
  772.     case KILL:
  773.         if (p->stage != 7) {
  774.         p->stage = 7;
  775.         p->stage_cnt = 13;
  776.         p->curr_object = 5307;
  777.         score += 100;
  778.         }
  779.         break;
  780.     } /* switch action */
  781.     ;
  782. }
  783.  
  784.  
  785. /*________________________________________________________________________
  786.  |
  787.  | do_spider - slow but nasty
  788.  |
  789.  | this routines looks like do_fish or do_bones
  790.  |
  791. */
  792.  
  793. static void do_spider(player_t *p, int action) {
  794.     node_t *nod;
  795.     int i;
  796.     int nextnod;
  797.     float dist, ndist;
  798.     player_t *play;
  799.     float v1[3];
  800.     
  801.     switch (action) {
  802.     case IDLE:                /* idle */
  803.         switch (p->stage) {
  804.         case 8:
  805.             p->stage = 0;
  806.         case 1:
  807.         case 2:
  808.         case 3:
  809.         case 4:
  810.         case 5:
  811.         case 6:
  812.         case 7:
  813.             if (p->currnode == p->prevnode) {
  814.             /* find the next node that makes the distance
  815.              * to the tracking point the closest possible
  816.              */
  817.             nod = the_nodes+ p->currnode;
  818.             nextnod = p->currnode;
  819.             dist =10;
  820.             i = (int) random() % 20;
  821.             if (nod->cnt > 2 && i < 8 + lifts_destroyed / 4) {
  822.                 if ( i == 0) {
  823.                 v1[0] = frand();
  824.                 v1[1] = v1[0]+0.0001;
  825.                 v1[2] = v1[1];
  826.                 vnormal(v1);
  827.                 } else if (i < 5) {
  828.                 /* this makes the spider even smarter */
  829.                 nextnod = p->currnode;
  830.                 dist = vdistance2(the_nodes[nextnod].pos,
  831.                     mouse_pos);
  832.                 nextnod = path_to_track(p->currnode, &dist);
  833.                 if (nextnod != p->currnode &&
  834.                     the_nodes[nextnod].player == null_player) {
  835.                     i = -1; /* mis-use i as a flag */
  836.                 } else {
  837.                     dist = 10;
  838.                     vcopy(mouse_pos, v1);
  839.                 }
  840.                 } else {
  841.                 vcopy(mouse_pos, v1);
  842.                 }
  843.             } else {
  844.                 vadd(p->pos, p->dir, v1);
  845.             }
  846.             if (i != -1 ) {
  847.                 i = 0;
  848.                 while (i < nod->cnt) {
  849.                 play = the_nodes[nod->c[i]].player;
  850.                 if (play != null_player && play->player_type != MOUSE) {
  851.                     i++;
  852.                     continue;
  853.                 }
  854.                 
  855.                 ndist = vdistance2(the_nodes[nod->c[i]].pos, v1);
  856.                 if (ndist < dist) {
  857.                     dist = ndist;
  858.                     nextnod = nod->c[i];
  859.                 }
  860.                 i++;
  861.                 }
  862.             }
  863.             if (nextnod == p->currnode) {
  864.                 /* stop moving the spider */
  865.                 p->stage++;
  866.             } else {
  867.                 p->stage++;
  868.                 p->currnode = nextnod;
  869.                 if (the_nodes[nextnod].player->player_type 
  870.                     == MOUSE) {
  871.                 do_step(p);
  872.                 sfx(SFX_DONK);
  873.                 do_mouse(the_nodes[nextnod].player, KILL);
  874.                 }
  875.                 vsub(the_nodes[nextnod].pos,
  876.                     the_nodes[p->prevnode].pos, v1);
  877.                 if (vdot(v1, p->dir) < 0) {
  878.                 vcross(the_nodes[nextnod].pos,
  879.                     the_nodes[p->prevnode].pos, p->dir);
  880.                 vnormal(v1);
  881.                 vscalar(v1, -0.3);
  882.                 vadd(p->dir, v1, p->dir);
  883.                 vnormal(p->dir);
  884.                 }
  885.                 do_step(p);
  886.                 p->curr_object = p->base_object + p->stage; 
  887.             }
  888.             } else {
  889.             /* keep on walking from prevnode to currnode */
  890.             p->stage++;
  891.             do_step(p); 
  892.             p->curr_object = p->base_object + p->stage; 
  893.             }
  894.             if (Lod < LIVE_FIGURES) {
  895.             p->curr_object = p->base_object;
  896.             }
  897.             break;
  898.         case 9:
  899.             if (p->stage_cnt--< 0) {
  900.             the_nodes[p->currnode].player = null_player;
  901.             remove_player(p);
  902.             monster_cnt--;
  903.             } else {
  904.             p->curr_object = 5409;
  905.             }
  906.         } /* switch stage */
  907.         break;
  908.     case KILL:
  909.         if (p->stage != 9) {
  910.         p->stage = 9;
  911.         p->curr_object = 5409;
  912.         p->stage_cnt = 13;
  913.         score += 25;
  914.         }
  915.         break;
  916.     
  917.     } /* switch action */
  918. }
  919.  
  920.  
  921. /*________________________________________________________________________
  922.  |
  923.  | do_fire - do the simple but beatiful fire animation
  924.  |
  925. */
  926.  
  927. static void do_fire(player_t *p, int action) {
  928.     /* there is currently only one action */
  929.     switch (action) {
  930.     case IDLE:             /* idle */
  931.         if (p->stage_cnt-- < 0) {
  932.         the_nodes[p->currnode].player = 0;
  933.         remove_player(p);
  934.         } else {
  935.         if (p->stage_cnt >= 0) {
  936.             p->curr_object++;
  937.             if (p->curr_object == 5804)
  938.             p->curr_object = 5801;
  939.         } else {
  940.             p->curr_object = 5800;
  941.         }
  942.         }
  943.         break;
  944.     } /* switch action */
  945.     
  946. }
  947.  
  948.  
  949. /*________________________________________________________________________
  950.  |
  951.  | do_mushroom - rather static animation
  952.  |
  953.  | this animation justs grows a mushroom, and after a period of time
  954.  | let it grow at a different, random position
  955.  |
  956. */
  957.  
  958. static void do_mushroom(player_t *p, int action) {
  959.     
  960.     int nodenum;
  961.     
  962.     switch (action) {
  963.     case IDLE:             /* idle */
  964.         switch (p->stage) {
  965.         case 1:
  966.             if (p->stage_cnt-- < 0) {
  967.             p->stage++;
  968.             p->curr_object = 5602;
  969.             p->stage_cnt = 2;
  970.             } else {
  971.             p->curr_object = 5601;
  972.             }
  973.             break;
  974.         case 2:
  975.             if (p->stage_cnt-- < 0) {
  976.             p->stage++;
  977.             p->curr_object = 5603;
  978.             p->stage_cnt = 2;
  979.             } else {
  980.             p->curr_object = 5602;
  981.             }
  982.             break;
  983.         case 3:
  984.             if (p->stage_cnt--< 0) {
  985.             p->stage = 6;
  986.             p->curr_object = 5604;
  987.             p->stage_cnt = 20 + (int)(random() % 250);
  988.             } else {
  989.             p->curr_object = 5603;
  990.             }
  991.             break;
  992.         case 6:
  993.             if (p->stage_cnt--< 0) {
  994.             p->stage = 7;
  995.             p->curr_object = 5603;
  996.             p->stage_cnt = 2;
  997.             } else {
  998.             p->curr_object = 5604;
  999.             }
  1000.             break;
  1001.         case 7:
  1002.             if (p->stage_cnt--< 0) {
  1003.             p->stage = 8;
  1004.             p->curr_object = 5602;
  1005.             p->stage_cnt = 2;
  1006.             } else {
  1007.             p->curr_object = 5603;
  1008.             }
  1009.             break;
  1010.         case 8:
  1011.             if (p->stage_cnt--< 0) {
  1012.             p->stage = 4;
  1013.             p->curr_object = 5601;
  1014.             p->stage_cnt = 2;
  1015.             } else {
  1016.             p->curr_object = 5602;
  1017.             }
  1018.             break;
  1019.         case 5:
  1020.             /* showing score */
  1021.             if (p->stage_cnt-- >= 0) {
  1022.             p->curr_object = 5605;
  1023.             return;
  1024.             }
  1025.             /* else run through */
  1026.         case 4:
  1027.             if (p->stage_cnt-- < 0) {
  1028.             the_nodes[p->currnode].player = null_player;
  1029.             nodenum = randnod();
  1030.             p->currnode = nodenum;
  1031.             p->prevnode = nodenum;
  1032.             p->stage_cnt = 2;
  1033.             p->curr_object = 5601;
  1034.             p->stage = 1;
  1035.             vcopy (the_nodes[nodenum].pos, p->pos);
  1036.             the_nodes[nodenum].player = p;        
  1037.             vdirection(p->pos,
  1038.                 the_nodes[the_nodes[nodenum].c[0]].pos, p->dir);
  1039.             } else {
  1040.             p->curr_object = 5601;
  1041.             }
  1042.             
  1043.         } /* switch stage */
  1044.         if (Lod < LIVE_FIGURES) {
  1045.         p->curr_object = p->base_object;
  1046.         }
  1047.         break;
  1048.     case KILL:
  1049.         if (p->stage != 5) {
  1050.         p->stage = 5;
  1051.         p->curr_object = 5605;
  1052.         p->stage_cnt = 13;
  1053.         score +=10;
  1054.         }
  1055.         break;
  1056.     } /* action switch */
  1057. }
  1058.  
  1059.  
  1060. /*________________________________________________________________________
  1061.  |
  1062.  | do_bomb - animate the bomb
  1063.  |
  1064.  | let it grow, animate the fire, and explode. When it explodes, it calls
  1065.  | build_fire, to give it the destructive power, normaly assiociated with
  1066.  | this type of equipment. This bomb is however fireproof, in that it does
  1067.  | not explode when heated in the fire of other bombs.
  1068.  |
  1069. */
  1070.  
  1071. static void do_bomb(player_t *p, int action) {
  1072.     int nodn;
  1073.     int power;
  1074.     float x;
  1075.     
  1076.     
  1077.     switch (action) {
  1078.     case IDLE:             /* idle */
  1079.         switch (p->stage) {
  1080.         case 1:
  1081.             if (p->stage_cnt-- < 0) {
  1082.             p->stage++;
  1083.             p->stage_cnt = 0;
  1084.             p->curr_object = 5502;
  1085.             } else {
  1086.             p->curr_object = 5501;
  1087.             }
  1088.             break;
  1089.         case 2:
  1090.             if (p->stage_cnt-- < 0) {
  1091.             p->stage++;
  1092.             p->stage_cnt = 0;
  1093.             p->curr_object = 5503;
  1094.             } else {
  1095.             p->curr_object = 5502;
  1096.             }
  1097.             break;
  1098.         case 3:
  1099.             if (p->stage_cnt-- < 0) {
  1100.             p->stage++;
  1101.             p->stage_cnt = 8;
  1102.             p->curr_object = 5504;
  1103.             } else {
  1104.             p->curr_object = 5503;
  1105.             }
  1106.             break;
  1107.         case 4:
  1108.             if (p->stage_cnt-- < 0) {
  1109.             p->stage++;
  1110.             p->stage_cnt = 8;
  1111.             p->curr_object = 5506;
  1112.             } else { 
  1113.             p->curr_object = 5504 + (p->stage_cnt & 1);
  1114.             }
  1115.             break;            
  1116.         case 5:
  1117.             if (p->stage_cnt-- < 0) {
  1118.             p->stage++;
  1119.             p->stage_cnt = 8;
  1120.             p->curr_object = 5508;
  1121.             } else { 
  1122.             p->curr_object = 5506 + (p->stage_cnt & 1);
  1123.             }
  1124.             break;            
  1125.         case 6:
  1126.             if (p->stage_cnt-- < 0) {
  1127.             p->stage++;
  1128.             p->stage_cnt = 8;
  1129.             p->curr_object = 5510;
  1130.             } else { 
  1131.             p->curr_object = 5507 + (p->stage_cnt & 1);
  1132.             }
  1133.             break;            
  1134.         case 7:
  1135.             if (p->stage_cnt-- < 0) {
  1136.             p->stage++;
  1137.             p->stage_cnt = 8;
  1138.             p->curr_object = 5511;
  1139.             } else {
  1140.             p->curr_object = 5510 + (p->stage_cnt & 1);
  1141.             }
  1142.             break;            
  1143.         case 8:
  1144.             /* explode */
  1145.             /* find position of explosion */
  1146.             x = rotmat[0][0] * p->pos[0] + rotmat[1][0] * p->pos[1] +
  1147.                 rotmat[2][0] * p->pos[2];
  1148.             if (x < -0.3) {
  1149.             x = -1;
  1150.             } else if (x > 0.3) {
  1151.             x = 1;
  1152.             } else
  1153.             x = 0;
  1154.             sfx_pan(SFX_EXPLOSION, (int) x);
  1155.             power = (int)(random() % 3) + 4;
  1156.             the_nodes[p->currnode].player = 0;
  1157.             nodn = p->currnode;
  1158.             remove_player(p);
  1159.             build_fire(nodn, power); 
  1160.             return;
  1161.         case 9:
  1162.             /* do nothing */
  1163.             ;
  1164.             break;
  1165.         }
  1166.     }
  1167.     if (Lod < LIVE_FIGURES) {
  1168.     p->curr_object = p->base_object;
  1169.     }
  1170. }
  1171.  
  1172.  
  1173. /*________________________________________________________________
  1174.  |
  1175.  | build_fire - create the nodes that show the fireballs
  1176.  |
  1177.  | this is a little recursive routine, that buils the fire on
  1178.  | selected nodes, starting from the node given as parameter.
  1179.  | Fire does not go through the door of the elevator, everything
  1180.  | else (except fire itself) is simply killed)
  1181.  | 
  1182.  */
  1183.  
  1184. static void build_fire(int nodnum, int power) {
  1185.     node_t *nod;
  1186.     int i;
  1187.     int nextn;
  1188.     player_t *play;
  1189.     
  1190.     nod = &(the_nodes[nodnum]);
  1191.     if (--power < 0 || nod->player->player_type == DOOR)
  1192.     return;
  1193.     if (nod->player->player_type != FIRE) {
  1194.     play = add_player(FIRE, nodnum, nod->c[0]);
  1195.     play->curr_object = 5801 + power % 3;
  1196.     } else {
  1197.     nod->player->stage_cnt = obj_definitions[FIRE].stage_cnt;
  1198.     }
  1199.     for (i = 0; i < nod->cnt; i++) {
  1200.     nextn = nod->c[i];
  1201.     if (the_nodes[nextn].player != null_player) {
  1202.         do_player(the_nodes[nextn].player, KILL);
  1203.     }
  1204.     }
  1205.     for (i=0; i< nod->cnt; i++) {
  1206.     build_fire(nod->c[i], power);
  1207.     }
  1208. }
  1209.  
  1210.  
  1211. /*_________________________________________________________________________
  1212.  |
  1213.  | do_lift - make the lift behave as it should
  1214.  | 
  1215.  | it pops up the elevator, opens the doors, creates monsters, closes the
  1216.  | door, and has some tricky handling to make a door impossible to
  1217.  | penetrate when it is closed.
  1218.  |
  1219. */
  1220.  
  1221. static void do_lift(player_t *p, int action) {
  1222.     int monster;
  1223.     player_t *newp;
  1224.     int door;
  1225.     int nodenum;
  1226.     float x;
  1227.     
  1228.     switch (action) {
  1229.     case IDLE:             /* idle */
  1230.         switch (p->stage) {
  1231.         
  1232.         case 1:
  1233.             /* lift is inactive */
  1234.             p->curr_object = 5706;
  1235.             break;
  1236.         case 2:
  1237.             if (p->stage_cnt-- < 0) {
  1238.             p->stage = 3;
  1239.             p->stage_cnt = 4;
  1240.             p->curr_object = 5702;
  1241.             /* pick a monster to generate */
  1242.             if (monster_cnt < MAXMONSTER ) {
  1243.                 monster = (int)(random() %
  1244.                     (25 + lifts_destroyed));
  1245.                 
  1246.                 if (monster >= 24 || lifts_destroyed == 11) {
  1247.                 monster = BONES;
  1248.                  
  1249.                 } else if (monster >= 19 ) {
  1250.                 monster = FISH;
  1251.                 } else {
  1252.                 monster = SPIDER;
  1253.                 }
  1254.                 /* don't created a monster when something else is
  1255.                  * at that position (bomb, mouse, other monster ) 
  1256.                  */
  1257.                 if (the_nodes[the_nodes[p->currnode].c[0]].player ==
  1258.                     null_player) {
  1259.                 newp = add_player(monster,  
  1260.                     the_nodes[p->currnode].c[0],
  1261.                     the_nodes[the_nodes[p->currnode].c[0]].c[0]
  1262.                     );
  1263.                 newp->stage_cnt = 20;
  1264.                 }
  1265.                 monster_cnt++;
  1266.             }
  1267.             } else {
  1268.             p->curr_object = 5701;
  1269.             }
  1270.             break;
  1271.         case 3:
  1272.             if (p->stage_cnt-- < 0) {
  1273.             p->stage = 4;
  1274.             p->stage_cnt = 4;
  1275.             p->curr_object = 5703;
  1276.             } else {
  1277.             p->curr_object = 5702;
  1278.             }
  1279.             break;
  1280.         case 4:
  1281.             if (p->stage_cnt-- < 0) {
  1282.             p->curr_object = 5704;
  1283.             /* open the door, by removing the DOOR actor */
  1284.             door = the_nodes[the_nodes[p->currnode].c[0]].c[0];
  1285.             the_nodes[door].player = null_player;
  1286.             p->stage_cnt = 30 + (int)(random() % 
  1287.                 (60- 2*lifts_destroyed));
  1288.             p->stage = 5;
  1289.             } else {
  1290.             p->curr_object = 5703;
  1291.             }
  1292.             break;
  1293.         case 5:
  1294.             if (p->stage_cnt-- < 0 ) {
  1295.             door = the_nodes[the_nodes[p->currnode].c[0]].c[0];
  1296.             if (the_nodes[door].player != null_player) {
  1297.                 /* cannot close the door someone is blocking */
  1298.                 return;
  1299.             }
  1300.             the_nodes[door].player = door_player;
  1301.             p->stage++;
  1302.             p->stage_cnt = 3;
  1303.             p->curr_object = 5703;
  1304.             } else {
  1305.             p->curr_object = 5704;
  1306.             }
  1307.             break;            
  1308.         case 6:
  1309.             if (p->stage_cnt-- < 0) {
  1310.             p->stage++;
  1311.             p->stage_cnt = 3;
  1312.             p->curr_object = 5702;
  1313.             } else {
  1314.             p->curr_object = 5703;
  1315.             }
  1316.             break;            
  1317.         case 7:
  1318.             if (p->stage_cnt-- < 0) {
  1319.             /* if another elevator is active, and nothing is trapped
  1320.              * inside then close down this elevator.
  1321.              */
  1322.             if (p->currnode != active_lift && 
  1323.                 (the_nodes[the_nodes[p->currnode].c[0]].player ==
  1324.                 null_player) &&
  1325.                 (the_nodes[the_nodes[p->currnode].c[1]].player ==
  1326.                 null_player)) {
  1327.                 /* shut down this lift */
  1328.                 p->stage=11;
  1329.                 p->stage_cnt = 2;
  1330.                 p->curr_object = 5700;
  1331.                 allow_bombs = 1;
  1332.             } else {
  1333.                 /* else set up the elevator to open again
  1334.                  * after some random interval, which gets
  1335.                  * shorter during the game
  1336.                  */
  1337.                 p->stage = 2;
  1338.                 p->stage_cnt = 60 - lifts_destroyed * 2.5 +
  1339.                 (int)(random() % (40 - lifts_destroyed * 2));
  1340.                 p->curr_object = 5701;
  1341.             }
  1342.             } else {
  1343.             p->curr_object = 5702;
  1344.             }
  1345.             break;            
  1346.         case 8:
  1347.             if (p->stage_cnt-- < 0) {
  1348.             door = the_nodes[the_nodes[p->currnode].c[0]].c[0];
  1349.             if (the_nodes[door].player != null_player &&
  1350.                 the_nodes[door].player->player_type != DOOR) {
  1351.                 /* cannot close the door someone is blocking */
  1352.                 do_player(the_nodes[door].player, KILL);
  1353.             } 
  1354.             p->stage = 9;
  1355.             p->curr_object = 5705;
  1356.             the_nodes[door].player = door_player;
  1357.             } else {
  1358.             p->curr_object = 5707;
  1359.             }
  1360.             break;
  1361.         case 9:
  1362.             /* crashed and stay crashed */
  1363.             p->curr_object = 5705;
  1364.             break;
  1365.         case 10:
  1366.             if (p->stage_cnt-- < 0) {
  1367.             p->stage = 2;
  1368.             p->stage_cnt = 20 + (int)(random() % 20) - lifts_destroyed;
  1369.             p->curr_object = 5701;
  1370.             }
  1371.             break;
  1372.         case 11:
  1373.             if (p->stage_cnt-- < 0) {
  1374.             p->stage = 1;
  1375.             p->curr_object = 5706;
  1376.             }
  1377.             break;
  1378.         case 12:
  1379.             if (p->stage_cnt-- < 0) {
  1380.             p->stage = 2;
  1381.             p->stage_cnt = 20 - lifts_destroyed +
  1382.                 (int)(random() % (20 - lifts_destroyed));
  1383.             p->curr_object = 5701;
  1384.             
  1385.             } else {
  1386.             p->curr_object = 5700;
  1387.              }
  1388.             break;
  1389.         case 13:
  1390.             /* special case, pops up elevator, generate mouse 
  1391.              * and closes down elevator as soon as mouse leaves
  1392.              * the elevator; some trickery is involved
  1393.              * to prevent bombs during this stage
  1394.              */
  1395.              if (p->stage_cnt-- < 0) {
  1396.              p->stage = 14;
  1397.              p->stage_cnt = 2;
  1398.              p->curr_object = 5700;
  1399.                  sfx_pan(SFX_LIFT, 0);
  1400.              } else {
  1401.              active_lift = -1;
  1402.              p->curr_object = 5706;
  1403.              }
  1404.              break;
  1405.         case 14:
  1406.             if (p->stage_cnt-- < 0) {
  1407.             p->stage = 15;
  1408.             p->stage_cnt = 2;
  1409.             p->curr_object = 5702;
  1410.             /* pick a monster to generate */
  1411.             newp = add_player(MOUSE, 
  1412.                 the_nodes[p->currnode].c[0],
  1413.                 the_nodes[the_nodes[p->currnode].c[0]].c[0]);
  1414.                 newp->stage_cnt = 10;
  1415.             } else {
  1416.             p->curr_object = 5701;
  1417.             }
  1418.             break;
  1419.         case 15:
  1420.             if (p->stage_cnt-- < 0) {
  1421.             p->stage = 16;
  1422.             p->stage_cnt = 2;
  1423.             p->curr_object = 5703;
  1424.             } else {
  1425.             p->curr_object = 5702;
  1426.             }
  1427.             break;
  1428.         case 16:
  1429.             if (p->stage_cnt-- < 0) {
  1430.             p->curr_object = 5704;
  1431.             /* open the door, by removing the DOOR actor */
  1432.             door = the_nodes[the_nodes[p->currnode].c[0]].c[0];
  1433.             the_nodes[door].player = null_player;
  1434.             p->stage_cnt = 0;
  1435.             p->stage = 17;
  1436.             trackpoint[0] = 0; trackpoint[1] = 0; trackpoint[2] = 1;
  1437.             } else {
  1438.             p->curr_object = 5703;
  1439.             }
  1440.             break;
  1441.         case 17:
  1442.             /* wait for mouse to leave elevator */
  1443.             door = the_nodes[the_nodes[p->currnode].c[0]].c[0];
  1444.             if (the_nodes[door].player == null_player &&
  1445.             (the_nodes[the_nodes[p->currnode].c[0]].player ==
  1446.                 null_player) && the_nodes[door].player == 
  1447.                 null_player) {
  1448.             the_nodes[door].player = door_player;
  1449.             p->stage = 18;
  1450.             p->stage_cnt = 2;
  1451.             p->curr_object = 5703;
  1452.             } else {
  1453.             p->curr_object = 5704;
  1454.             }
  1455.             break;            
  1456.         case 18:
  1457.             if (p->stage_cnt-- < 0) {
  1458.             p->stage = 7;
  1459.             p->stage_cnt = 2;
  1460.             p->curr_object = 5702;
  1461.             putbomb = 0;
  1462.             } else {
  1463.             p->curr_object = 5703;
  1464.             }
  1465.             break;            
  1466.         } /* switch stage */
  1467.         break;
  1468.     case MAGIC:
  1469.         /* you have stepped on a magic node, so pop up the elevator */
  1470.         switch (p->stage) {
  1471.         case 1:
  1472.             /* find position of lift on screen */
  1473.             x = rotmat[0][0] * p->pos[0] + rotmat[1][0] * p->pos[1] +
  1474.                 rotmat[2][0] * p->pos[2];
  1475.             if (x < -0.3) {
  1476.             x = -1;
  1477.             } else if (x > 0.3) {
  1478.             x = 1;
  1479.             } else
  1480.             x = 0;
  1481.             sfx_pan(SFX_LIFT, (int) x);
  1482.             p->stage = 12;
  1483.             active_lift = p->currnode;
  1484.             p->stage_cnt = 0;
  1485.             p->curr_object = 5700;
  1486.             /* add a few mushrooms to make the game more difficult */
  1487.             nodenum = randnod();
  1488.             add_player(MUSH, nodenum, nodenum);
  1489.             nodenum = randnod();
  1490.             add_player(MUSH, nodenum, nodenum);
  1491.         break;
  1492.         }
  1493.         break;
  1494.     case KILL:
  1495.         if (p->stage != 8) {
  1496.         p->stage = 8;
  1497.         p->curr_object = 5707;
  1498.         p->stage_cnt = 13;
  1499.         score += 250;
  1500.         lifts_destroyed++;
  1501.         if (lifts_destroyed == 12)  {
  1502.             /* end of this level */
  1503.             /* this is real silly and has to improve a lot */
  1504.             sleep(3);
  1505.             sfx(SFX_BEEP);
  1506.             sleep(2);
  1507.             printf("\nyou finished the demo level\n");
  1508.             printf("\nYour score was: %d (not so bad)\n", score);
  1509.             printf("\n\nthank you for playing.\n");
  1510.             printf("\n    Frans van Hoesel  Xtreme Graphics Software\n");
  1511.             printf("\n     (hoesel@chem.rug.nl)");
  1512.             gexit();
  1513.             end_sound();
  1514.             exit(0);
  1515.         }
  1516.         }
  1517.         break;
  1518.         
  1519.     } /* switch action */
  1520.  
  1521. }
  1522.  
  1523.  
  1524. /*__________________________________________________________________________
  1525.  |
  1526.  | do_player - depending on the type of actor, call the correct routine
  1527.  |
  1528. */
  1529.  
  1530. void do_player(player_t *p, int action) {
  1531.     switch (p->player_type) {
  1532.     case MOUSE:                /* mouse */
  1533.         do_mouse(p, action);
  1534.         break;
  1535.     case FISH:                /* fish */
  1536.         do_fish(p, action);
  1537.         break;
  1538.     case BONES:                /* bones */
  1539.         do_bones(p, action);
  1540.         break;
  1541.     case SPIDER:                /* spider */
  1542.         do_spider(p, action);
  1543.         break;
  1544.     case BOMB:                /* bomb */
  1545.         do_bomb(p, action);
  1546.         break;
  1547.     case MUSH:                /* mushroom */
  1548.         do_mushroom(p, action);
  1549.         break;
  1550.     case LIFT:                /* lift */
  1551.         do_lift(p, action);
  1552.         break;
  1553.     case FIRE:            /* fire */
  1554.         do_fire(p, action);
  1555.         break;
  1556.     /* case DOOR is not needed */
  1557.     } /* switch player_type */
  1558. }
  1559.  
  1560.  
  1561. /*_________________________________________________________________________
  1562.  |
  1563.  | add_player - make a new actor
  1564.  |
  1565. */
  1566.  
  1567. static player_t *add_player(int ptyp, int currnode, int prevnode) {
  1568.     player_t *newplayer;
  1569.  
  1570.     newplayer = (player_t *) malloc (sizeof(player_t));
  1571.     memcpy(newplayer, obj_definitions + ptyp, sizeof(player_t));
  1572.     last_player->next = newplayer;
  1573.     newplayer->prev = last_player;
  1574.     last_player = newplayer;
  1575.     vcopy(the_nodes[currnode].pos, newplayer->pos);
  1576.     vdirection(the_nodes[prevnode].pos, the_nodes[currnode].pos,
  1577.         newplayer->dir);
  1578.     if (newplayer->stage_cnt < 0) {
  1579.     newplayer->stage_cnt = (int)(random() % (- newplayer->stage_cnt))
  1580.         - newplayer->stage_cnt / 4;
  1581.     }
  1582.     if (newplayer->speed == 0) {
  1583.     newplayer->prevnode = currnode;
  1584.     } else {
  1585.     newplayer->prevnode = prevnode;
  1586.     }
  1587.     the_nodes[currnode].player = newplayer;
  1588.     newplayer->currnode = currnode;
  1589.     return newplayer;
  1590. }
  1591.  
  1592.  
  1593. /*_________________________________________________________________________
  1594.  |
  1595.  | remove_player - delete an actor
  1596.  |
  1597. */
  1598.  
  1599. static void remove_player(player_t *p) {
  1600.     if (p == last_player) {
  1601.     last_player = p->prev;
  1602.     }
  1603.     /* prevnode and currnode may be equal... who cares */
  1604.     the_nodes[p->currnode].player = null_player;
  1605.     the_nodes[p->prevnode].player = null_player;
  1606.     if (p->next != NULL) {
  1607.     p->next->prev = p->prev;
  1608.     }
  1609.     p->prev->next = p->next;
  1610.     free (p);
  1611. }
  1612.  
  1613.  
  1614. /*_________________________________________________________________________
  1615.  |
  1616.  | players_action - let all defined actors do some animation
  1617.  |
  1618. */
  1619.  
  1620. void players_action(void) {
  1621.     player_t *play;
  1622.     play = first_player->next;
  1623.     /* if you are dead, keep animating possible fire; the rest doesn't
  1624.      * animate anymore
  1625.      */
  1626.     if (mouse_dead) {
  1627.     do {
  1628.         if (play->player_type == FIRE) {
  1629.         do_player(play, IDLE);
  1630.         }
  1631.         play = play->next;
  1632.     } while (play != NULL);
  1633.     } else {
  1634.     do {
  1635.         do_player(play, IDLE);
  1636.         play = play->next;
  1637.     } while (play != NULL);
  1638.     }
  1639. }
  1640.  
  1641.  
  1642. /*_________________________________________________________________________
  1643.  |
  1644.  | draw_players - draw all defined actors
  1645.  |
  1646.  | it also does some trivial culling. for this it needs the actual 
  1647.  | height of the actors. When the level of detail is very low, so the
  1648.  | walls are just lines, you may see the effect of culling a bit too
  1649.  | early, but this I thought was acceptable.
  1650. */
  1651.  
  1652. void draw_players(Matrix mat, Matrix invmat) {
  1653.  
  1654.     Matrix m;
  1655.     
  1656.     player_t *play, *p;
  1657.     float *p1, *d1, v1[3];
  1658.     static float height[] = { 0, -0.33, -0.3, -0.35, -0.08, -0.17,
  1659.         -0.2, -0.38, -0.2, 0};
  1660.  
  1661.     if (mouse_dead != 0) {
  1662.     if (mouse_dead >= 25) {
  1663.         putbomb = 0;
  1664.         if (mouse_dead == 25) {
  1665.         play = first_player->next;
  1666.         do {
  1667.             p = play->next;
  1668.             free(p);
  1669.             play = p;
  1670.         } while (play != NULL);
  1671.         memcpy(first_player, obj_definitions, sizeof(player_t));        
  1672.         last_player = first_player;
  1673.         null_player = first_player;
  1674.         last_player = first_player;
  1675.         init_special();
  1676.         monster_cnt = 0;
  1677.         lifts_destroyed = 0;
  1678.         active_lift = -1;
  1679.         }
  1680.         trackpoint[0] = 0; trackpoint[1] = 1; trackpoint[2] = 0;
  1681.         prev_trackpoint[0] = 0; prev_trackpoint[1] = 1; prev_trackpoint[2] = 0;
  1682.         if (score > highscore) {
  1683.         highscore = score;
  1684.         }
  1685.         return;
  1686.     } else if (mouse_dead == 6) {
  1687.         sfx(SFX_PLANET);
  1688.     }
  1689.     }
  1690.     multmatrix(mat);
  1691.     play = first_player->next;
  1692.     m[0][3] = 0;
  1693.     m[1][3] = 0;
  1694.     m[2][3] = 0;
  1695.     m[3][0] = 0;
  1696.     m[3][1] = 0;
  1697.     m[3][2] = 0;
  1698.     m[3][3] = 1;    
  1699.     do {
  1700.     if (play->player_type == DOOR) {
  1701.         play = play->next;
  1702.         continue;
  1703.     }
  1704.     p1 = play->pos;
  1705.     /* some crude culling for the backside of the sphere */
  1706.     if ( invmat[2][0]* p1[0] + invmat[2][1] * p1[1] + invmat[2][2] * p1[2]
  1707.         < height[play->player_type]) {
  1708.         play = play->next;
  1709.         continue;
  1710.     }
  1711.     d1 = play->dir;
  1712.     pushmatrix();
  1713.     translate(p1[0], p1[1], p1[2]);
  1714.     vcross(p1, d1, v1);
  1715.     vnormal(v1);
  1716.     m[0][0] = v1[0];
  1717.     m[0][1] = v1[1];
  1718.     m[0][2] = v1[2];
  1719.     m[1][0] = p1[0];
  1720.     m[1][1] = p1[1];
  1721.     m[1][2] = p1[2];
  1722.     m[2][0] = d1[0];
  1723.     m[2][1] = d1[1];
  1724.     m[2][2] = d1[2];
  1725.     multmatrix(m);
  1726.         callobj(play->curr_object);
  1727.     play = play->next;
  1728.     popmatrix();
  1729.     } while (play != NULL);
  1730. }
  1731.  
  1732. /*________________________________________________________________________
  1733.  |
  1734.  | draw_status - status indicator, during loading of data
  1735.  |
  1736. */
  1737.  
  1738. static void draw_status(int i) {
  1739.     ortho2(0,300, 0, 300);
  1740.     cpack(0x000020ff);
  1741.     rectf(174, 100, 286, 111);
  1742.     cpack(0x00009090);
  1743.     rectf(175,101, 285, 110);
  1744.     cpack(0x00004090);
  1745. #ifdef ANIMATED
  1746.     rectf(175, 101, 175+i*110/67.0, 110);
  1747. #else
  1748.     rectf(175, 101, 175+i*110/37.0, 110);
  1749. #endif
  1750. }
  1751.  
  1752.  
  1753. /*_________________________________________________________________________
  1754.  |
  1755.  | init_players - initialize all the players data
  1756.  |
  1757.  | read the object definitions from the data files; update the
  1758.  | status display, and when there are redraw, or quit events during this
  1759.  | phase, act accordingly.
  1760.  |
  1761. */
  1762. void init_players(void) {
  1763.     int obj;
  1764.     int cnt = 0;
  1765.     
  1766.     /*mallopt(M_MXFAST, sizeof(player_t))
  1767.       mallopt(M_FREEHD, 1)
  1768.     */;
  1769.     
  1770.     obj = 5800;
  1771.     obj_definitions[8].base_object = obj;
  1772.     obj_definitions[8].curr_object = obj+1; draw_status(cnt++); do_event();
  1773.     read_object_file("obj/fire0.iv", obj++); draw_status(cnt++); do_event();
  1774.     read_object_file("obj/fire1.iv", obj++); draw_status(cnt++); do_event();
  1775.     read_object_file("obj/fire2.iv", obj++); draw_status(cnt++); do_event();
  1776.     read_object_file("obj/fire3.iv", obj++); draw_status(cnt++); do_event();
  1777.  
  1778.     obj = 5100;
  1779.     obj_definitions[1].base_object = obj;
  1780.     obj_definitions[1].curr_object = obj+1;
  1781.     read_object_file("obj/mouseblok.iv", obj++); draw_status(cnt++); do_event();
  1782.     read_object_file("obj/mouse0.iv", obj++); draw_status(cnt++); do_event();
  1783. #ifdef ANIMATED
  1784.     read_object_file("obj/mouse1.iv", obj++); draw_status(cnt++); do_event();
  1785.     read_object_file("obj/mouse2.iv", obj++); draw_status(cnt++); do_event();
  1786.     read_object_file("obj/mouse3.iv", obj++); draw_status(cnt++); do_event();
  1787.     read_object_file("obj/mouse4.iv", obj++); draw_status(cnt++); do_event();
  1788.     read_object_file("obj/mouse5.iv", obj++); draw_status(cnt++); do_event();
  1789.     read_object_file("obj/mouse6.iv", obj++); draw_status(cnt++); do_event();
  1790.     read_object_file("obj/mousea.iv", obj++); draw_status(cnt++); do_event();
  1791.     read_object_file("obj/mouseb.iv", obj++); draw_status(cnt++); do_event();
  1792.     read_object_file("obj/mousec.iv", obj++); draw_status(cnt++); do_event();
  1793. #else
  1794.     makeobj(obj++); callobj(5101); closeobj();
  1795.     makeobj(obj++); callobj(5101); closeobj();
  1796.     makeobj(obj++); callobj(5101); closeobj();
  1797.     makeobj(obj++); callobj(5101); closeobj();
  1798.     makeobj(obj++); callobj(5101); closeobj();
  1799.     makeobj(obj++); callobj(5101); closeobj();
  1800.     makeobj(obj++); callobj(5101); closeobj();
  1801.     makeobj(obj++); callobj(5101); closeobj();
  1802.     makeobj(obj++); callobj(5101); closeobj();
  1803. #endif
  1804.  
  1805.     obj = 5200;
  1806.     obj_definitions[2].base_object = obj;
  1807.     obj_definitions[2].curr_object = obj+1;
  1808.     read_object_file("obj/fishblok.iv", obj++); draw_status(cnt++); do_event();
  1809.     read_object_file("obj/fish1.iv", obj++); draw_status(cnt++); do_event();
  1810. #ifdef ANIMATED
  1811.     read_object_file("obj/fish2.iv", obj++); draw_status(cnt++); do_event();
  1812.     read_object_file("obj/fish3.iv", obj++); draw_status(cnt++); do_event();
  1813.     read_object_file("obj/fish4.iv", obj++); draw_status(cnt++); do_event();
  1814.     read_object_file("obj/fish5.iv", obj++); draw_status(cnt++); do_event();
  1815.     read_object_file("obj/fish6.iv", obj++); draw_status(cnt++); do_event();
  1816.     read_object_file("obj/fish7.iv", obj++); draw_status(cnt++); do_event();
  1817. #else
  1818.     makeobj(obj++); callobj(5201); closeobj();
  1819.     makeobj(obj++); callobj(5201); closeobj();
  1820.     makeobj(obj++); callobj(5201); closeobj();
  1821.     makeobj(obj++); callobj(5201); closeobj();
  1822.     makeobj(obj++); callobj(5201); closeobj();
  1823.     makeobj(obj++); callobj(5201); closeobj();
  1824. #endif
  1825.     read_object_file("obj/50.iv", obj++); draw_status(cnt++); do_event();
  1826.  
  1827.     obj = 5300;
  1828.     obj_definitions[3].base_object = obj;
  1829.     obj_definitions[3].curr_object = obj+1;
  1830.     read_object_file("obj/bonesblok.iv", obj++); draw_status(cnt++); do_event();
  1831.     read_object_file("obj/bones1.iv", obj++); draw_status(cnt++); do_event();
  1832. #ifdef ANIMATED
  1833.     read_object_file("obj/bones2.iv", obj++); draw_status(cnt++); do_event();
  1834.     read_object_file("obj/bones3.iv", obj++); draw_status(cnt++); do_event();
  1835.     read_object_file("obj/bones4.iv", obj++); draw_status(cnt++); do_event();
  1836.     read_object_file("obj/bones5.iv", obj++); draw_status(cnt++); do_event();
  1837.     read_object_file("obj/bones6.iv", obj++); draw_status(cnt++); do_event();
  1838. #else
  1839.     makeobj(obj++); callobj(5301); closeobj();
  1840.     makeobj(obj++); callobj(5301); closeobj();
  1841.     makeobj(obj++); callobj(5301); closeobj();
  1842.     makeobj(obj++); callobj(5301); closeobj();
  1843.     makeobj(obj++); callobj(5301); closeobj();
  1844. #endif
  1845.     read_object_file("obj/100.iv", obj++); draw_status(cnt++); do_event();
  1846.  
  1847.     obj = 5400;
  1848.     obj_definitions[4].base_object = obj;
  1849.     obj_definitions[4].curr_object = obj+1;
  1850.     read_object_file("obj/spiderblok.iv", obj++); draw_status(cnt++); do_event();
  1851.     read_object_file("obj/spider9.iv", obj++); draw_status(cnt++); do_event();
  1852. #ifdef ANIMATED
  1853.     read_object_file("obj/spider2.iv", obj++); draw_status(cnt++); do_event();
  1854.     read_object_file("obj/spider3.iv", obj++); draw_status(cnt++); do_event();
  1855.     read_object_file("obj/spider4.iv", obj++); draw_status(cnt++); do_event();
  1856.     read_object_file("obj/spider5.iv", obj++); draw_status(cnt++); do_event();
  1857.     read_object_file("obj/spider6.iv", obj++); draw_status(cnt++); do_event();
  1858.     read_object_file("obj/spider7.iv", obj++); draw_status(cnt++); do_event();
  1859.     read_object_file("obj/spider8.iv", obj++); draw_status(cnt++); do_event();
  1860. #else
  1861.     makeobj(obj++); callobj(5401); closeobj();
  1862.     makeobj(obj++); callobj(5401); closeobj();
  1863.     makeobj(obj++); callobj(5401); closeobj();
  1864.     makeobj(obj++); callobj(5401); closeobj();
  1865.     makeobj(obj++); callobj(5401); closeobj();
  1866.     makeobj(obj++); callobj(5401); closeobj();
  1867.     makeobj(obj++); callobj(5401); closeobj();
  1868. #endif
  1869.     read_object_file("obj/25.iv", obj++); draw_status(cnt++); do_event();
  1870.  
  1871.     obj = 5500;
  1872.     obj_definitions[5].base_object = obj;
  1873.     obj_definitions[5].curr_object = obj+1;
  1874.     read_object_file("obj/bombblok.iv", obj++); draw_status(cnt++); do_event();
  1875. #ifdef ANIMATED
  1876.     read_object_file("obj/bomba.iv", obj++); 
  1877.     read_object_file("obj/bombb.iv", obj++); draw_status(cnt++); do_event();
  1878.     read_object_file("obj/bombc.iv", obj++);
  1879.     read_object_file("obj/bomb1.iv", obj++);
  1880.     read_object_file("obj/bomb2.iv", obj++); draw_status(cnt++); do_event();
  1881.     read_object_file("obj/bomb3.iv", obj++); 
  1882.     read_object_file("obj/bomb4.iv", obj++);
  1883.     read_object_file("obj/bomb5.iv", obj++); draw_status(cnt++); do_event();
  1884.     read_object_file("obj/bomb6.iv", obj++);
  1885.     read_object_file("obj/bomb7.iv", obj++);
  1886.     read_object_file("obj/bomb8.iv", obj++); draw_status(cnt++); do_event();
  1887. #else
  1888.     read_object_file("obj/bomb1.iv", obj++);
  1889.     makeobj(obj++); callobj(5501); closeobj();
  1890.     makeobj(obj++); callobj(5501); closeobj();
  1891.     makeobj(obj++); callobj(5501); closeobj();
  1892.     makeobj(obj++); callobj(5501); closeobj();
  1893.     makeobj(obj++); callobj(5501); closeobj();
  1894.     makeobj(obj++); callobj(5501); closeobj();
  1895.     makeobj(obj++); callobj(5501); closeobj();
  1896.     makeobj(obj++); callobj(5501); closeobj();
  1897.     makeobj(obj++); callobj(5501); closeobj();
  1898.     makeobj(obj++); callobj(5501); closeobj();
  1899. #endif    
  1900.     read_object_file("obj/15.iv", obj++); draw_status(cnt++); do_event();
  1901.  
  1902.     obj = 5600;
  1903.     obj_definitions[6].base_object = obj;
  1904.     obj_definitions[6].curr_object = obj+4;
  1905.     read_object_file("obj/mushblok.iv", obj++); draw_status(cnt++); do_event();
  1906. #ifdef ANIMATED
  1907.     read_object_file("obj/mushr1.iv", obj++); 
  1908.     read_object_file("obj/mushr2.iv", obj++); draw_status(cnt++); do_event();
  1909.     read_object_file("obj/mushr3.iv", obj++); 
  1910.     read_object_file("obj/mushr4.iv", obj++); draw_status(cnt++); do_event();
  1911. #else
  1912.     read_object_file("obj/mushr4.iv", obj++); draw_status(cnt++); do_event();
  1913.     makeobj(obj++); callobj(5601); closeobj();
  1914.     makeobj(obj++); callobj(5601); closeobj();
  1915.     makeobj(obj++); callobj(5601); closeobj();
  1916. #endif
  1917.     read_object_file("obj/10.iv", obj++); draw_status(cnt++); do_event();
  1918.  
  1919.     obj = 5700;
  1920.     obj_definitions[7].base_object = obj;
  1921.     obj_definitions[7].curr_object = obj+1;
  1922.     read_object_file("obj/lift5.iv", obj++); draw_status(cnt++); do_event();
  1923.     read_object_file("obj/lift0.iv", obj++); draw_status(cnt++); do_event();
  1924.     read_object_file("obj/lift1.iv", obj++); draw_status(cnt++); do_event();
  1925.     read_object_file("obj/lift2.iv", obj++); draw_status(cnt++); do_event();
  1926.     read_object_file("obj/lift3.iv", obj++); draw_status(cnt++); do_event();
  1927.     read_object_file("obj/lift4.iv", obj++); draw_status(cnt++); do_event();
  1928.     read_object_file("obj/lift6.iv", obj++); draw_status(cnt++); do_event();
  1929.     read_object_file("obj/250.iv", obj++); draw_status(cnt++); do_event();
  1930.  
  1931.     obj = 7000;
  1932.     read_object_file("obj/dead.iv", obj++); draw_status(cnt++); do_event();
  1933.     
  1934.     obj = 8000;
  1935.     read_object_file("obj/0.iv", obj++);
  1936.     read_object_file("obj/1.iv", obj++); draw_status(cnt++); do_event();
  1937.     read_object_file("obj/2.iv", obj++); 
  1938.     read_object_file("obj/3.iv", obj++);
  1939.     read_object_file("obj/4.iv", obj++);
  1940.     read_object_file("obj/5.iv", obj++); draw_status(cnt++); do_event();
  1941.     read_object_file("obj/6.iv", obj++); 
  1942.     read_object_file("obj/7.iv", obj++); 
  1943.     read_object_file("obj/8.iv", obj++); 
  1944.     read_object_file("obj/9.iv", obj++); draw_status(cnt++); do_event();
  1945.     
  1946.  
  1947.     /* add the mouse as a predefined player */
  1948.     first_player = (player_t *) malloc (sizeof(player_t));
  1949.     memcpy(first_player, obj_definitions, sizeof(player_t));        
  1950.     last_player = first_player;
  1951.     null_player = first_player;
  1952.     /* time to make a pass over the nodes and to
  1953.      * create some initial monsters
  1954.      */
  1955.     init_special();
  1956. }
  1957.  
  1958.  
  1959. /*_________________________________________________________________________
  1960.  |
  1961.  | init_special - relate the node data to the actor data
  1962.  |
  1963.  | for all nodes in the data base, created an actor or a magic node
  1964. */
  1965.  
  1966. static void init_special(void) {
  1967.     node_t *nod;
  1968.     special_t spec;
  1969.     int i;
  1970.     
  1971.     nod = the_nodes;
  1972.     for (i=0; i< the_nnodes; i++) {
  1973.     spec = nod->special;
  1974.     
  1975.     if (spec.all) {
  1976.         if (spec.b.ptype != 0) {
  1977.         if (spec.b.ndir != 0 ) {
  1978.             /* point to previous node */
  1979.             nod->player = add_player(spec.b.ptype, i, nod->c[1]);
  1980.         } else {
  1981.             /* point to next node */
  1982.             nod->player = add_player(spec.b.ptype, i, nod->c[0]);
  1983.         }
  1984.         if (spec.b.ptype == DOOR) {
  1985.             door_player = nod->player;
  1986.         } else if (spec.b.ptype == MUSH) {
  1987.             nod->player->stage = 6;
  1988.             nod->player->stage_cnt = random() % 150 + 40;
  1989.         }
  1990.         } else {
  1991.         nod->player = null_player;
  1992.         }
  1993.     } else {
  1994.         nod->player = null_player;
  1995.     }
  1996.     nod++;
  1997.     }
  1998.     nod = & the_nodes[1420];
  1999.     nod->player->stage = 13;
  2000.     active_lift = -1;
  2001.     nod->player->stage_cnt = 5;
  2002.     nod->player->curr_object = 5706;
  2003.     allow_bombs = 0;
  2004. }
  2005.